package com.newsnetwork.article.controller;

import com.newsnetwork.api.BaseController;
import com.newsnetwork.api.controller.article.ArticlePortalControllerApi;
import com.newsnetwork.api.controller.user.UserControllerApi;
import com.newsnetwork.article.service.ArticlePortalService;
import com.newsnetwork.article.service.ArticleService;
import com.newsnetwork.grace.result.CommonJSONResult;
import com.newsnetwork.pojo.Article;
import com.newsnetwork.pojo.vo.AppUserVO;
import com.newsnetwork.pojo.vo.ArticleDetailVO;
import com.newsnetwork.pojo.vo.IndexArticleVO;
import com.newsnetwork.utils.IPUtil;
import com.newsnetwork.utils.JsonUtils;
import com.newsnetwork.utils.PagedGridResult;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author: HuangDekai
 * @date: 2022/11/12 11:34
 * @version: 1.0
 * @since: jdk8
 * @description: 门户端文章业务的controller
 */
@RestController
public class ArticlePortalController extends BaseController implements ArticlePortalControllerApi {

    private static final Logger log = LoggerFactory.getLogger(ArticlePortalController.class);

    @Autowired
    private ArticleService articleService;
    @Autowired
    private ArticlePortalService articlePortalService;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public CommonJSONResult list(String keyword,
                                 Integer category,
                                 Integer page,
                                 Integer pageSize) {
        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult result = articlePortalService.queryIndexArticleList(keyword, category, page, pageSize);

        // 将作者信息等用户信息部分 远程调用 相关服务进行获取, 并放入到 result 中
        result = rebuildArticleGrid(result);

        return CommonJSONResult.ok(result);
    }

    /**
     * 将作者信息等用户信息部分 远程调用获取, 并放入到 result 中
     * @param result 包含 (List<Article>) result.getRows() 的 PagedGridResult
     * @return 设置好 List<IndexArticleVO> 的 PagedGridResult
     */
    private PagedGridResult rebuildArticleGrid(PagedGridResult result) {
//START 这里后面会使用 SpringCloud 进行远程调用
        /**
         * 查询文章发布者的用户信息和头像
         * 从 性能角度, 不应该连表查询, 因此使用另一条单表查询
         * 从 微服务角度, 这部分功能是在用户模块里的, 这里之后应该远程调用那部分微服务
         */
        List<Article> list = (List<Article>) result.getRows();
        // 构建发布者id列表, 去重
        Set<String> idSet = new HashSet<>();
        List<String> idList = new ArrayList<>();
        list.stream().forEach(
                article -> {
                    // 1.1 构建发布者的set
                    idSet.add(article.getPublishUserId());
                    // 1.2 构建文章id的list
                    idList.add(REDIS_ARTICLE_READ_COUNTS + ":" + article.getId());
                });
        // 发起redis的mget批量查询api，获得对应的值
        List<String> readCountsRedisList = redisOperator.mget(idList);
        // 发起远程调用(restTemplate), 请求用户服务, 获得用户(idSet)的列表
        List<AppUserVO> publisherList = getPublisherList(idSet);


        // 拼接两个 list, 充足文章列表
        List<IndexArticleVO> indexArticleList = new ArrayList<>();
        for (int i = 0 ; i < list.size() ; i ++) {
            IndexArticleVO indexArticleVO = new IndexArticleVO();
            Article article = list.get(i);
            BeanUtils.copyProperties(article, indexArticleVO);
            //从 publisherList 中获取发布者的基本信息
            AppUserVO publisher = getUserIfPublisher(article.getPublishUserId(), publisherList);
            indexArticleVO.setPublisherVO(publisher);
            // 重新组装设置文章列表中的阅读量
            String redisCountsStr = readCountsRedisList.get(i);
            int readCounts = 0;
            if (StringUtils.isNotBlank(redisCountsStr)) {
                readCounts = Integer.valueOf(redisCountsStr);
            }
            indexArticleVO.setReadCounts(readCounts);


            indexArticleList.add(indexArticleVO);
        }
        result.setRows(indexArticleList);
//END
        return result;
    }

    /**
     * 根据 publisherId 从 publisherList 获取对应 id 的用户 pojo
     * @param publisherId 发布者的id
     * @param publisherList 发布者列表
     * @return 对应 id 的用户信息 / null
     */
    private AppUserVO getUserIfPublisher(String publisherId, List<AppUserVO> publisherList) {
        for (AppUserVO userVO : publisherList) {
            if (userVO.getId().equalsIgnoreCase(publisherId)) {
                return userVO;
            }
        }
        return null;
    }


    /**
     * 注入服务发现, 可以获得已经注册的服务相关信息
     */
    //@Autowired
    //private DiscoveryClient discoveryClient;
    @Autowired
    private UserControllerApi userControllerApi;

    /**
     * 发起远程调用，获得用户的基本信息
     * @param idSet 发布者列表
     * @return
     */
    private List<AppUserVO> getPublisherList(Set idSet) {
//        String serviceId = "SERVICE-USER";
//        //List<ServiceInstance> instanceList = discoveryClient.getInstances(serviceId);
//        // 只有一个 SERVICE-USER, 因此 get(0) 即可获取实例
//        //ServiceInstance userService = instanceList.get(0);
//
//        //String userServiceUrlExecute = "http://user.newsnetwork.com:8003/user/queryByIds?userIds=" + JsonUtils.objectToJson(idSet);
//        // 动态地址拼接
//        //String userServiceUrlExecute = "http://" + userService.getHost() + ":" + userService.getPort() + "/user/queryByIds?userIds=" + JsonUtils.objectToJson(idSet);
//        String userServiceUrlExecute = "http://" + serviceId + "/user/queryByIds?userIds=" + JsonUtils.objectToJson(idSet);
//        ResponseEntity<CommonJSONResult> responseEntity = restTemplate.getForEntity(userServiceUrlExecute, CommonJSONResult.class);
//        CommonJSONResult bodyResult = responseEntity.getBody();
        CommonJSONResult bodyResult = userControllerApi.queryByIds(JsonUtils.objectToJson(idSet));
        List<AppUserVO> publisherList = null;
        if (bodyResult.getStatus() == 200) {
            String userJson = JsonUtils.objectToJson(bodyResult.getData());
            publisherList = JsonUtils.jsonToList(userJson, AppUserVO.class);
        }
        return publisherList;
    }

    /**
     * todo 将该接口的实现 改为按以浏览量和评论量为算法基础的排序
     * 目前仅通过时间排序查询出热闻
     * @return 热闻列表
     */
    @Override
    public CommonJSONResult hotList() {
        return CommonJSONResult.ok(articlePortalService.queryHotList());
    }


    /**
     * 分页查询作者名下的文章
     * @param writerId 作者id
     * @param page 第几页
     * @param pageSize 每页有几条记录
     * @return 分页好的该作者的文章
     */
    @Override
    public CommonJSONResult queryArticleListOfWriter(String writerId, Integer page, Integer pageSize) {
        if (page == null) {
            page = COMMON_START_PAGE;
        }
        if (pageSize == null) {
            pageSize = COMMON_PAGE_SIZE;
        }

        PagedGridResult result = articlePortalService.queryArticleListOfWriter(writerId, page, pageSize);
        result = rebuildArticleGrid(result);

        return CommonJSONResult.ok(result);
    }

    /**
     * 查询作者近期佳文
     * @param writerId 作者id
     * @return 倒序的该作者的最近 几篇文章
     */
    @Override
    public CommonJSONResult queryGoodArticleListOfWriter(String writerId) {
        return CommonJSONResult.ok(articlePortalService.queryGoodArticleListOfWriter(writerId));
    }

    @Override
    public CommonJSONResult detail(String articleId) {
        ArticleDetailVO detailVO = articlePortalService.queryDetail(articleId);

        Set<String> idSet = new HashSet();
        idSet.add(detailVO.getPublishUserId());
        List<AppUserVO> publisherList = getPublisherList(idSet);

        if (!publisherList.isEmpty()) {
            detailVO.setPublishUserName(publisherList.get(0).getNickname());
        }
        Integer countsFromRedis = getCountsFromRedis(REDIS_ARTICLE_READ_COUNTS + ":" + articleId);
        detailVO.setReadCounts(countsFromRedis == null ? 0 : countsFromRedis);

        return CommonJSONResult.ok(detailVO);
    }

    @Override
    public Integer readCounts(String articleId) {
        Integer countsFromRedis = getCountsFromRedis(REDIS_ARTICLE_READ_COUNTS + ":" + articleId);
        return countsFromRedis == null ? 0 : countsFromRedis;
    }

    @Override
    public CommonJSONResult readArticle(String articleId, HttpServletRequest request) {

        String userIp = IPUtil.getRequestIp(request);
        // 设置针对当前用户ip的永久存在的key，存入到redis，表示该ip的用户已经阅读过了，无法累加阅读量
        redisOperator.setnx(REDIS_ALREADY_READ + ":" +  articleId + ":" + userIp, userIp);
        // 阅读数累加1
        redisOperator.increment(REDIS_ARTICLE_READ_COUNTS + ":" + articleId, 1);
        return CommonJSONResult.ok();
    }
}
